#coding=utf-8
#auth:beck shen
#date:2017-10-24


from __future__ import absolute_import

from . import _string
from pytw.core.tasklet import Tasklet

import httplib
import urlparse
from urllib import urlencode

from twisted.internet.ssl import ClientContextFactory
from twisted.web.http_headers import Headers
from twisted.web.client import (
                BrowserLikePolicyForHTTPS,
                Agent,
                readBody,
                _requireSSL,
                _DeprecatedToCurrentPolicyForHTTPS
                )
from twisted import internet
from twisted.internet import reactor


class _WebClientContextFactory(ClientContextFactory):
    
    """
    不验证服务端证书
    """

    def getContext(self, hostname, port):
        ctx = ClientContextFactory.getContext(self)
        return ctx


class _BrowserLikePolicyForHTTPS(BrowserLikePolicyForHTTPS):

    """
    OPENSSL cacert路径问题
    """

    CA_FILE = '/etc/ssl/certs/ca-bundle.crt'
    
    @_requireSSL
    def creatorForNetloc(self, hostname, port):
        ctx = internet.ssl.optionsForClientTLS(hostname.decode("ascii"),
                trustRoot=self._trustRoot)
        ctx._ctx.load_verify_locations(self.CA_FILE)
        return ctx


class HTTPClient(object):

    """
    HTTP或者HTTPS请求client基类
    uri:http://www.example/test
    method:POST、GET
    body:发送的body类容
    params:dict类型，将会urlencode添加至uri后面
    headers:dict类型，发送的http请求头
    tiemout:tcp超时时间
    body_encode:发送body编码方式
    check_cacert:是否验证对方证书
    """
    
    def __init__(self, uri,
                method = 'GET', 
                body = '', 
                params = None,
                headers = None, 
                timeout = 30,
                body_encode = 'utf-8',
                check_cacert = True):
        self.method = method
        self.timeout = timeout

        self._process_uri(uri, params)
        self._process_headers(headers)
        self._process_body(body, body_encode)
        self._process_context_factory(check_cacert)

    def _process_uri(self, uri, params):
        """
        处理uri以及params
        """
        if not params:
            self.uri = uri
        else:
            self.uri = '%s?%s'%(uri, urlencode(params))

    def _process_headers(self, headers):
        """
        处理请求头
        """
        self.headers = Headers()
        if not headers:
            return
        for k, v in headers.items():
            if not isinstance(v, list):
                v = [v,]
            self.headers.setRawHeaders(k, v)

    def _process_body(self, body, body_encode):
        """
        处理body
        """
        if isinstance(body, unicode):
            body = body.encode(body_encode, 'ignore')
        self.body = _string.StringProducer(body)

    def _process_context_factory(self, check_cacert):
        """
        HTTPS请求使用
        """
        if not check_cacert:
            ctx_factory = _WebClientContextFactory()
            self.context_factory = _DeprecatedToCurrentPolicyForHTTPS(ctx_factory)
        else:
            self.context_factory = _BrowserLikePolicyForHTTPS()

    def request(self):
        """
        发送请求
        """ 
        agent = Agent(reactor,
                    contextFactory = self.context_factory,
                    connectTimeout = self.timeout)
        request = agent.request(self.method, self.uri, self.headers, self.body)
        return request
    
    def get_response(self, request):
        """
        获取返回，可能需要处理internet.error.ConnectError
        进行数据重新发送处理，其他错误应该记录日志
        """
        response = Tasklet.current.get_result(request)
        body_defer = readBody(response)
        body = Tasklet.current.get_result(body_defer)
        #将body赋值给response.content
        response.content = body
        return response


class HTTPSClient(HTTPClient):

    """
    HTTPS请求
    """


class SyncHTTPClient(HTTPClient):

    """
    在线程中使用，同步发送HTTP请求
    """

    def _process_uri(self, uri, params):
        """
        处理uri以及params
        """
        sc = urlparse.urlsplit(uri)
        self.host = sc.netloc
        self.uri = sc.path
        if params:
            self.uri = '%s?%s'%(self.uri, urlencode(params))

    def _process_headers(self, headers):
        """
        处理请求头
        """
        self.headers = headers.copy()

    def _process_body(self, body, body_encode):
        """
        处理body
        """
        if isinstance(body, unicode):
            body = body.encode(body_encode, 'ignore')
        self.body = body

    def _process_context_factory(self, check_cacert):
        """
        HTTPS请求使用
        """
        pass

    def request(self):
        """
        发送请求
        """
        request = httplib.HTTPConnection(self.host, timeout = self.timeout)
        request.connect()
        request.request(self.method, self.uri, self.body, self.headers) 
        return request 

    def get_response(self, request):
        """
        获取返回
        """
        response = request.getresponse()
        content = response.read()
        response.content = content
        return response

